package cn.jinjimi.app.managers;

import android.text.TextUtils;

import cn.jinjimi.base.preference.PreferenceManager;
import cn.jinjimi.base.util.GsonUtils;
import cn.jinjimi.base.util.MD5Utils;
import cn.jinjimi.base.util.StringUtils;
import cn.jinjimi.app.AccountManager;
import cn.jinjimi.app.bean.Constants;
import cn.jinjimi.app.controller.AppConfigureController;
import cn.jinjimi.app.controller.event.LoginSuccessEvent;
import cn.jinjimi.app.controller.event.LogoutEvent;
import cn.jinjimi.app.controller.event.UpdateModuleConfigEvent;
import cn.jinjimi.domain.Dispatcher;
import cn.jinjimi.domain.ServiceManager;
import cn.jinjimi.domain.data.net.PageService;
import cn.jinjimi.domain.store.ConfigStore;
import cn.jinjimi.app.entity.AppConfig.AppAlert;
import cn.jinjimi.app.entity.AppConfig.AppModule;
import cn.jinjimi.app.entity.AppConfig.HomeEntranceList;
import cn.jinjimi.app.entity.AppConfig.HomeCateList;
import cn.jinjimi.app.modules.Resource.NetResourceManager;
import cn.jinjimi.app.modules.Resource.Resource;
import cn.jinjimi.app.modules.Theme.ZdbTheme;
import cn.jinjimi.app.modules.Theme.ZdbThemeManager;
import cn.jinjimi.app.modules.adv.Adv;
import cn.jinjimi.app.modules.crm.CRM;
import cn.jinjimi.app.modules.drp.Drp;
import cn.jinjimi.app.store.entity.NoticeEntity;
import cn.jinjimi.app.bean.SharePrefKeys;

import org.greenrobot.eventbus.Subscribe;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

import bolts.Task;

/**
 * Created by Roy
 * 全局配置项管理类
 * Date: 16/5/11
 * @author zhenhua
 */
public class ConfigManager {

    private static ConfigManager instance;
    private static Map<String, Long> mUpdateTimes = new HashMap<>();
    private static Map<String, Object> mCachedConfigs = new HashMap<>();
    private static Map<String, Boolean> mAppAlertState = new HashMap<>();

    public static ConfigManager getInstance() {
        if (instance == null) {
            instance = new ConfigManager();
        }
        return instance;
    }

    public ConfigManager() {
        ServiceManager.getService(Dispatcher.class).register(this);
    }

    public void destroy() {
        ServiceManager.getService(Dispatcher.class).unregister(this);
        instance = null;
    }

    public void save() {

    }

    /**
     * 更新模块的配置数据
     *
     * @param appModule
     * @param getConfig 是否从服务端同步配置信息
     */
    public void updateModule(AppModule appModule, boolean getConfig) {
        if (appModule == null)
            return;

        if (StringUtils.isEmpty(appModule.config) && StringUtils.isNotEmpty(appModule.link) && getConfig) {
            AppConfigureController.getConfigModule(appModule.link);
            return;
        }

        if (StringUtils.isEmpty(appModule.config) || StringUtils.isEmpty(appModule.name))
            return;

        if (StringUtils.isNotEmpty(appModule.name)) {
            if (AppModule.ModuleTabs.equals(appModule.name)) {
                cacheConfig(AppModule.ModuleTabs, HomeEntranceList.fetchHomeEntranceList());
            } else if (AppModule.ModuleToolbars.equals(appModule.name)) {
                cacheConfig(AppModule.ModuleToolbars, HomeCateList.fetchHomeCateList());
            } else if (AppModule.ModuleDrp.equals(appModule.name)) {
                cacheConfig(AppModule.ModuleDrp, GsonUtils.fromJson(appModule.config, Drp.Config.class));
                Drp.getInstance().createConfig();
            } else if (AppModule.ModuleAdv.equals(appModule.name)) {
                cacheConfig(AppModule.ModuleAdv, Adv.getInstance().createConfig());
            } else if (AppModule.ModuleAlert.equals(appModule.name)) {
                GuideManager.getInstance().setConfig(appModule.config);
            } else if (AppModule.ModuleCRM.equals(appModule.name)) {
                cacheConfig(AppModule.ModuleCRM, GsonUtils.fromJson(appModule.config, CRM.Config.class));
            } else if (AppModule.ModuleResource.equals(appModule.name)) {
                cacheConfig(AppModule.ModuleResource, Resource.getInstance().createConfig());
                NetResourceManager.getInstance().checkResource();
            } else if(AppModule.ModuleBundle.equals(appModule.name)){
                cacheConfig(AppModule.ModuleBundle, Resource.getInstance().createBundle());
                NetResourceManager.getInstance().checkBundles();
            } else if (AppModule.ModuleTheme.equals(appModule.name)) {
                cacheConfig(AppModule.ModuleTheme, ZdbTheme.getInstance().createConfig());
                ZdbThemeManager.getInstance().checkConfig();
            }
        }
    }

    private void createNotice(String code, AppAlert alert) {
        if (shouldShow(alert)) {
            NoticeManager.createNotice(
                    NoticeEntity.TypeAlert, alert.id, code,
                    (AppAlert.TARGET_NEW.equals(alert.target) || AppAlert.TARGET_USER.equals(alert.target)) && AccountManager.getInstance().isLogin()
                            ? AccountManager.getInstance().getAccount().ssoid : null);
        }
    }

    /**
     * 根据模块名称从缓存中获取配置项目
     *
     * @param name
     * @return
     */
    public String getConfig(final String name) {
        String cached = ServiceManager.getService(ConfigStore.class).getConfig(name);
        if (TextUtils.isEmpty(cached) || isConfigExpired(name)) {
            fetchConfig(name);
        }
        return cached;
    }

    /**
     * 根据模块名称从网络获取配置项目
     *
     * @param name
     */
    public void fetchConfig(final String name) {
        Task.callInBackground(new Callable<AppModule>() {
            @Override
            public AppModule call() throws Exception {
                return ServiceManager.getService(ConfigStore.class)
                        .fetchConfigOfModule(name);
            }
        });
    }

    private boolean isConfigExpired(String name) {
        boolean expired = false;
        if (AppModule.ModuleDrp.equals(name)) {
            Long date = mUpdateTimes.get(name);
            expired = date == null || date + Constants.MIN_1 < System.currentTimeMillis();
            if (expired) {
                mUpdateTimes.put(name, System.currentTimeMillis());
            }
        }
        return expired;
    }


    private void cacheConfig(String key, Object config) {
        mCachedConfigs.put(key, config);
    }

    private Object getCachedConfig(String module) {
        return mCachedConfigs.get(module);
    }

    public void hasMainActivityStarted(boolean state) {
        PreferenceManager.setData(SharePrefKeys.PREF_MAIN_START, state);
    }

    public boolean hasMainActivityStarted() {
        return PreferenceManager.getBooleanData(SharePrefKeys.PREF_MAIN_START);
    }

    public AppAlert getAppAlert(String module) {
        if (module != null) {
            if (AppModule.ModuleDrp.equals(module)) {
                Drp.Config config = (Drp.Config) getCachedConfig(module);

                if (config == null) {
                    config = Drp.Config.create(getConfig(AppModule.ModuleDrp));
                    cacheConfig(AppModule.ModuleDrp, config);
                }

                if (config != null) {
                    if (shouldShow(config.alert)) {
                        return config.alert;
                    }
                }
            }
        }
        return null;
    }

    /**
     * 根据AppAlert.target检查是否需要显示
     *
     * @param alert
     * @return
     */
    public boolean shouldShow(AppAlert alert) {

        boolean isLogin = AccountManager.getInstance().isLogin();

        return alert != null && ((AppAlert.TARGET_ANONYMOUS.equals(alert.target) && !isLogin)
                || (AppAlert.TARGET_NEW.equals(alert.target) && isLogin && AccountManager.getInstance().isNewAccount())
                || (AppAlert.TARGET_USER.equals(alert.target) && isLogin)
        );
    }

    /**
     * 根据AppAlert.display检查是否需要显示
     *
     * @param alert
     * @return
     */
    public boolean shouldDisplay(AppAlert alert) {
        return alert != null && (
                (AppAlert.DISPLAY_ONCE.equals(alert.display) && !hasAlertShownBefore(alert))
                        || AppAlert.DISPLAY_EVERYTIME.equals(alert.display)
                        || AppAlert.DISPLAY_EVERYSESSION.equals(alert.display) && !hasAlertShownBeforeSessionStart(alert)
        );
    }

    /**
     * 根据AppAlert.display检查是否需要显示
     *
     * @param module
     * @return
     */
    public boolean shouldDisplay(String module) {
        return shouldDisplay(getAppAlert(module));
    }

    public boolean hasAlertShownBefore(AppAlert alert) {
        NoticeEntity notice = NoticeManager.getInstance().getNoticeById(alert.id);
        return notice == null || notice.hadShowed;
    }

    public boolean hasAlertShownBeforeSessionStart(AppAlert alert) {
        Boolean hasShown = mAppAlertState.get(getNewAlertId(alert.id));
        return hasShown != null && hasShown.equals(true);
    }

    public void markAlertHasShown(AppAlert alert) {
        if (alert != null) {
            if (AppAlert.DISPLAY_EVERYSESSION.equals(alert.display)) {
                mAppAlertState.put(getNewAlertId(alert.id), true);
            }
            NoticeManager.clickNoticeById(alert.id);
        }

    }

    public String getNewAlertId(String id) {
        String ssoid = AccountManager.getInstance().isLogin() ?
                AccountManager.getInstance().getAccount().ssoid : "";

        return MD5Utils.MD5(id + ssoid);
    }

    public void fetchConfigsFromRemote() {
        Task.callInBackground(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                ServiceManager.getService(PageService.class).getConfigs();
                return null;
            }
        });
    }

    @Subscribe
    public void onEvent(UpdateModuleConfigEvent event) {
        if (event != null && event.module != null) {
            updateModule(event.module, false);
        }
    }

    @Subscribe
    public void onEvent(LoginSuccessEvent event) {
        fetchConfigsFromRemote();
    }

    @Subscribe
    public void onEvent(LogoutEvent event) {
        fetchConfigsFromRemote();
    }

    public Drp.Config.GroupInsurance getGroupInsurance() {
        Object config = getCachedConfig(AppModule.ModuleDrp);
        if (config instanceof Drp.Config) {
            return ((Drp.Config) config).groupInsurance;
        }
        return null;
    }

}
